package rensoft.android.view.grid;

import static rensoft.java.lang.Lang.is;
import static rensoft.java.lang.Lang.no;

import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import rensoft.android.HasActivity;
import rensoft.android.HasActivityPresenter;
import rensoft.android.view.RequestPresenter;
import rensoft.android.view.requestdata.DataPresenter;
import rensoft.java.event.Event.EventRegistration;
import rensoft.java.event.Listener;
import rensoft.java.lang.Callback;
import rensoft.java.lang.Factory;

public class GridDataPresenter<RequestType extends IGridRequest> extends HasActivityPresenter
    implements DataPresenter<RequestType> {

  private int position;
  private GridRequestData<RequestType> data;
  public Factory<GridRowView<RequestType>> rowViewFactory;
  private int listViewId;
  private final RequestPresenter<RequestType> requestPresenter;
  private Callback<RequestType> loadListener;

  public GridDataPresenter(HasActivity hasActivity, String id, GridRequestData<RequestType> data,
      int loadingIndicatorId) {
    super(hasActivity);
    this.data = data;
    requestPresenter = new RequestPresenter<RequestType>(this, id, loadingIndicatorId);
  }

  public void load() {
    data.load(position);
    requestPresenter.sendRequest(data.getDataRequest());
  }

  @Override
  public void onSaveInstanceState(Bundle state) {
    super.onSaveInstanceState(state);
    if (is(getListView().getAdapter()))
      state.putInt(getListIndexStateId(), getListView().getFirstVisiblePosition());
    else state.putInt(getListIndexStateId(), position);
  }

  public void prependData(RowData rowdata) {
    data.prependData(rowdata);
    getListView().setAdapter(new ListAdapter(data.getAllCount()));
    getListView().setSelection(position);
  }

  public void reload() {
    data.reload();
    requestPresenter.sendRequest(data.getDataRequest());
  }

  public void setCreateRequestListener(final Callback<RequestType> callback) {
    data.setCreateRequestListener(new Callback<RequestType>() {
      @Override
      public void onCall(RequestType value) {
        callback.onCall(value);
      }
    });
  }

  public void setData(GridRequestData<RequestType> data) {
    this.data = data;
  }

  public void setFailedListener(Callback<RequestType> callback) {
    requestPresenter.setFailedListener(callback);
  }

  public void setListViewId(int listViewId) {
    this.listViewId = listViewId;
  }

  public void setLoadListener(Callback<RequestType> loadListener) {
    this.loadListener = loadListener;
  }

  public void setRowFactory(Factory<GridRowView<RequestType>> transactionRowFactory) {
    this.rowViewFactory = transactionRowFactory;
  }

  @Override
  protected void onCreate() {
    super.onCreate();
    listen(data.eventLoaded(), new Listener<RequestType>() {
      public void onEvent(EventRegistration registration, RequestType data) {
        if (!isPaused()) onDataLoaded(data);
      }
    });
  }

  @Override
  protected void onCreateRestore(Bundle state) {
    super.onCreateRestore(state);
    position = state.getInt(getListIndexStateId());
  }

  protected void onDataLoaded(RequestType request) {
    if (is(loadListener)) loadListener.onCall(request);
    getListView().setAdapter(new ListAdapter(data.getAllCount()));
    getListView().setSelection(position);
  }

  private String getListIndexStateId() {
    return this.getClass().getName() + "index";
  }

  private ListView getListView() {
    return getListView(listViewId);
  }

  private class ListAdapter extends BaseAdapter {
    private final int itemsCount;

    public ListAdapter(int allcount) {
      itemsCount = allcount;
    }

    public int getCount() {
      return itemsCount;
    }

    public Object getItem(int position) {
      return position;
    }

    public long getItemId(int position) {
      return position;
    }

    @SuppressWarnings("unchecked")
    public View getView(int position, View view, ViewGroup parent) {
      GridRowView<RequestType> rowView;
      if (no(view)) {
        rowView = rowViewFactory.create();
        view = rowView.asView();
        view.setTag(rowView);
      } else rowView = (GridRowView<RequestType>) view.getTag();
      rowView.load(data.getRowDataFor(position));
      return view;
    }

  }
}
